package main

import (
	"bufio"
	"encoding/csv"
	"fmt"
	"io"
	"log"
	"os"
	"path"
	"path/filepath"

	"gitee.com/yanxingshuyuan/backend/server/models"
	"gitee.com/yanxingshuyuan/backend/server/repositories"
	"gitee.com/yanxingshuyuan/backend/util"
	"github.com/jmoiron/sqlx"
	"github.com/spf13/viper"
)

type Config struct {
	DBString string `json:"dbstring"`
	DataDir  string `json:"datadir"`
}

func initConfig() *Config {
	viper.SetConfigType("toml")
	viper.SetConfigName("loader")
	viper.AddConfigPath(".")

	err := viper.ReadInConfig()
	if err != nil {
		log.Fatalf("fatal error: config file %s not found", err)
	}
	config := &Config{}
	config.DBString = viper.GetString("dbstring")
	if config.DBString == "" {
		log.Fatal("Bad Config: No Database String!\n")
		return config
	}
	viper.SetDefault("datadir", "./data/")
	config.DataDir = viper.GetString("datadir")
	return config
}

var matRepo *repositories.MatRepo
var peopleRepo *repositories.PeopleRepo

func loadBooks(data string) {

	pat := filepath.Join(data, "*_*")
	files, err := filepath.Glob(pat)
	if err != nil {
		fmt.Printf("error globing data files: %#v\n", data)
	}

	if len(files) == 0 {
		fmt.Printf("No files found for %v\n", pat)
	}

	for n, f := range files {
		fmt.Printf("book folder:%v,%v\n", n, f)

		loadBook(f)
	}

}

type Toc struct {
	N    string
	Name string
}

func loadBook(dir string) {
	dirname := util.GetTrimmedName(dir)
	name, author := util.ParsePair(dirname, "_")
	log.Printf("book:%v, author:%v", name, author)

	// 先输入作者信息
	person := peopleRepo.GetOrAddPerson(author, "")
	link := "@" + dirname
	// 再输入书籍的素材信息
	search := models.MatSearchForm{
		Title:  name,
		Kind:   models.KindBook,
		Author: person.ID,
		Table:  models.MatTableMats,
		Link:   link,
	}
	var bookMid int64
	mats := matRepo.SearchMats(search)
	if mats.Total > 0 {
		log.Print("Mat already exist, ignoring...\n")
		bookMid = mats.Mats[0].ID
	} else {
		mat := &models.MatForm{
			Mat: models.Mat{
				Title:  name,
				Kind:   models.KindBook,
				Format: models.MatFormatToc,
				Link:   link,
				Source: "©殆知阁",
			},
			Pids: person.ID,
		}
		log.Printf("adding mat: %#v\n", mat)
		matRepo.AddMat(mat)
		bookMid = mat.ID
	}
	// 对于目录中的每一章，输入其素材信息
	tocFile := path.Join(dir, "__TOC.csv")
	f, err := os.Open(tocFile)
	if err != nil {
		log.Printf("Error opening TOC file: %v\n", tocFile)
	}
	defer f.Close()

	reader := csv.NewReader(bufio.NewReader(f))
	order := 0
	for {
		line, err := reader.Read()
		if err == io.EOF {
			break
		} else if err != nil {
			log.Printf("error reading csv file: %v\n", tocFile)
			break
		}
		if line[0] == "0" { // 第一行是书籍的标题，跳过
			continue
		}
		toc := Toc{
			N:    line[0],
			Name: line[1],
		}
		log.Printf("toc: %#v\n", toc)

		// 再输入章节的素材信息
		chapLink := path.Join("@"+dirname, toc.N+".md")
		search := models.MatSearchForm{
			Title:  toc.Name,
			Kind:   models.KindChapter,
			Author: person.ID,
			Table:  models.MatTableMats,
			Link:   chapLink,
		}
		mats := matRepo.SearchMats(search)
		var chapMid int64
		if mats.Total > 0 {
			log.Print("Mat already exist, ignoring...\n")
			chapMid = mats.Mats[0].ID
			mat := &models.MatForm{
				Mat: models.Mat{
					ID:     chapMid,
					Title:  toc.Name,
					Kind:   models.KindChapter,
					Format: models.MatFormatFile,
					Link:   chapLink,
					Source: "©殆知阁",
				},
				Pids: person.ID,
			}
			log.Printf("updating mat: %#v\n", mat)
			matRepo.ModifyMat(mat)
		} else {
			mat := &models.MatForm{
				Mat: models.Mat{
					Title:  toc.Name,
					Kind:   models.KindChapter,
					Format: models.MatFormatFile,
					Link:   link,
					Source: "©殆知阁",
				},
				Pids: person.ID,
			}
			log.Printf("adding mat: %#v\n", mat)
			matRepo.AddMat(mat)
			chapMid = mat.ID
		}
		if chapMid != 0 {
			order = order + 1
			log.Printf("adding tree:%v, %v, %v\n", chapMid, bookMid, order)
			matRepo.AddTree(chapMid, bookMid, order)
		}
	}

}

func loadChapter(n int, file string) {

}

func main() {
	config := initConfig()

	db, err := sqlx.Connect("postgres", config.DBString)
	if err != nil {
		log.Fatal("Error connecting database:\n")
	}

	dir := config.DataDir

	tagRepo := repositories.NewTagRepo(db)
	matRepo = repositories.NewMatRepo(db, dir, tagRepo)
	peopleRepo = repositories.NewPeopleRepo(db)
	loadBooks(dir)
}
